package com.youlu.campus.wechat.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.Status;
import com.youlu.campus.entity.VO.req.QQWxRefundRequest;
import com.youlu.campus.entity.WechatMerchantConfig;
import com.youlu.campus.entity.domain.RefundOrderResult;
import com.youlu.campus.wechat.service.WeChatPayRefundService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

/**
 * 公钥退款
 *
 * @Description: PubKeyWeChatPayRefundServiceImpl
 * @Date 2025/10/20
 * @module PubKeyWeChatPayRefundServiceImpl
 * @author: su
 */
@Slf4j
public class PubKeyWeChatPayRefundServiceImpl implements WeChatPayRefundService {

    private RefundService refundService;

    /**
     * mongodb 数据库配置验证 md5  避免重复创建
     */
    private final String configMD5;

    public PubKeyWeChatPayRefundServiceImpl(String configMD5, WechatMerchantConfig wechatMerchantConfig) {
        this.configMD5 = configMD5;
        String merchantId = wechatMerchantConfig.getMerchantId();//商户号
        String privateKeyPath = wechatMerchantConfig.getPathPrivateKey();//商户 API 私钥路径
        String merchantSerialNumber = wechatMerchantConfig.getSerialNumber();//商户证书序列号
        String pubPath = wechatMerchantConfig.getPathPublicKey();//公钥路径
        String publicKeyId = wechatMerchantConfig.getPublicKeyId();//公钥id
        String apiV3Key = wechatMerchantConfig.getApiV3Key();//商户 APIV3 密钥

        //创建配置
        RSAPublicKeyConfig config = new RSAPublicKeyConfig.Builder()
                .merchantId(merchantId)
                .privateKeyFromPath(privateKeyPath)
                .publicKeyFromPath(pubPath)
                .publicKeyId(publicKeyId)
                .merchantSerialNumber(merchantSerialNumber)
                .apiV3Key(apiV3Key)
                .build();
        this.refundService = new RefundService.Builder().config(config).build();
    }

    @Override
    public String getConfigMD5() {
        return this.configMD5;
    }

    /**
     * 申请退款
     *
     * @param refundRequest
     * @return
     */
    @Override
    public RefundOrderResult applyRefund(QQWxRefundRequest refundRequest) {
        log.info("applyRefund request:{}", refundRequest);
        String outTradeNo = refundRequest.getOrderNo();//商户订单号
        String outRefundNo = refundRequest.getRefundNo();//商户退款单号
        long totalAmount = refundRequest.getTotalFee();//订单总金额（单位：分）
        long refundAmount = refundRequest.getRefundFee();//退款金额（单位：分）
        String refundReason = refundRequest.getDesc();//退款原因

        AmountReq amount = new AmountReq();
        amount.setTotal(totalAmount);
        amount.setRefund(refundAmount);
        amount.setCurrency("CNY");

        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(outTradeNo);
        request.setOutRefundNo(outRefundNo);
        request.setAmount(amount);
        request.setReason(refundReason);
        //request.setNotifyUrl("https://your.domain.com/refund/notify"); // 退款结果通知地址
        Refund refund = null;
        try {
            refund = refundService.create(request);
        } catch (ServiceException e) {
            String responseBody = e.getResponseBody();
            log.error("applyRefund error:{}", responseBody, e);
            if (!responseBody.contains("订单已全额退款")) {
                throw e;
            }
            refund = new Refund();
            refund.setStatus(Status.SUCCESS);
        }
        log.info("applyRefund result:{}", JSONObject.toJSONString(refund));
        if (Status.PROCESSING.equals(refund.getStatus())) {
            refund.setStatus(Status.SUCCESS);
        }
        RefundOrderResult refundOrderResult = new RefundOrderResult();
        BeanUtils.copyProperties(refundRequest, refundOrderResult);
        refundOrderResult.setResult_code(refund.getStatus().name());
        refundOrderResult.setRefund_id(refund.getRefundId());
        return refundOrderResult;
    }
}
